#include "e32_900.h"
#include "bsp_gpio.h"
#include "com_lora.h"
#include "bsp_uart.h"
#include "bsp_delay.h"
#include <stdio.h>
#include "crc16.h"
#include <string.h>
#include "SEGGER_RTT.h"

#define LORA_DEV_ADDR_H 0x00 /* 模块地址 */
#define LORA_DEV_ADDR_L 0x01

#define UART_BAUD_9600 0x03     /* 默认串口波特率 9600 */
#define UART_BAUD_115200 0x07

#define UART_PARITY_8N1 0x00 /* 默认 8N1 */
#define UART_PARITY_801 0x00
#define UART_PARITY_8E1 0x00

#define AIR_RATE_2_P_4K 0x02 /* 空中速率,2.4K */
#define AIR_RATE_4_P_8K 0x03 /* 空中速率,4.8K */
#define AIR_RATE_9_P_6K 0x04
#define AIR_RATE_19_P_2K 0x05

struct lora_e32_900 lora_dev = {
    .config_reg = {
        .head = 0xC0,
        .add_h = LORA_DEV_ADDR_H,
        .add_l = LORA_DEV_ADDR_L,

        .sped.parity_bit = UART_PARITY_8N1,
        .sped.baud = UART_BAUD_9600,
        .sped.air_rate = AIR_RATE_2_P_4K,

        .chan.reseved = 0x00,
        .chan.channel = 0x07,

        .option.modbus = 1,
        .option.io_mode = 1,
        .option.wake_up = 0x00,
        .option.fec = 1,
        .option.power = 0,
    },
};

static uint8_t default_config[6] = { 
    0xC0,
    0x00,
    0x01,
    0x1C,
    0x06,
    0x44,
};

/*******************************************************************
* 函数名: e32_900_config_work_mode()
* 功 能: 设置模块运行模式
* 输 入: 
*     
* 输 出: 
*******************************************************************/
int8_t e32_900_config_work_mode(enum mode_type mode)
{
    if (mode > LORA_MODE_TOTAL)
    {
        return -1;
    }
    switch (mode)
    {
    case LORA_MODE_NORMAL:
        LORA_M0(0);LORA_M1(0); 
        break;
    case LORA_MODE_WOR:
        LORA_M0(1);LORA_M1(0); 
        break;
    case LORA_MODE_CONFIG:
        LORA_M0(0);LORA_M1(1); 
        break;
    case LORA_MODE_SLEEP:
        LORA_M0(1);LORA_M1(1); 
        break;
    default:
        break;
    }
    
    uint8_t times = 0;
    do{
        if(++times >= 10)
        {
            SEGGER_RTT_printf(0, "lora aux error.\r\n");
            return -2;
        }
        bsp_delay_ms(4);
    }while (!LORA_AUX());

    return 0;
}

/*******************************************************************
* 函数名: e32_900_send_require_cmd()
* 功 能: 模块发送读取寄存器指令
* 输 入: 
*     
* 输 出: 
*******************************************************************/
static void e32_900_send_require_cmd(uint8_t reg, uint8_t len)
{
    uint8_t data[3] = {0};

    data[0] = LORA_CMD_READ_REG;
    data[1] = LORA_CMD_READ_REG;
    data[2] = LORA_CMD_READ_REG;

    bsp_uart_driver_t* drv = lora_drv();
    drv->ops.write(drv, data, sizeof(data));
}

/*******************************************************************
* 函数名: e32_900_write_reg_cmd()
* 功 能: 写模块寄存器指令
* 输 入: 
*     
* 输 出: 
*******************************************************************/
static void e32_900_write_reg_cmd(uint8_t* buff, uint8_t len)
{
    if(len > 6)
        return;

    bsp_uart_driver_t* drv = lora_drv();
    drv->ops.write(drv, buff, len);
}

/*******************************************************************
* 函数名: e32_900_receive_hanlder()
* 功 能: 接收到的数据,单字节处理
* 输 入: 
*     
* 输 出: 
*******************************************************************/
static uint8_t e32_900_config_process(uint8_t byte, uint8_t* buff)
{
    #define FRAME_HEADER_1 0xC0
    static uint8_t number = 0;
    static uint8_t pos = 0;
    uint8_t res = 0;

    switch (number)
    {
        case 0:  /* 找帧头 */
        if(FRAME_HEADER_1 == byte)
        {
            number = 1;
            buff[0] = byte;
            pos = 1;
        } 
        break;
        case 1: /* 存数据 */
        buff[pos++] = byte;
        if(pos >= 6)
        {
            number = 0;
            pos = 0;
            res = 6; 
        }
        break;
    default:
        break;
    }
    return res;
}

/*******************************************************************
* 函数名: e32_900_config()
* 功 能: 配置模块参数
* 输 入: 
*     
* 输 出: 
*******************************************************************/
int16_t e32_900_config(void)
{
    static uint8_t times = 0;

    bsp_uart_driver_t* drv = lora_drv();
    /* 设置模块为配置模式 */
    do{
        int8_t res = e32_900_config_work_mode(LORA_MODE_SLEEP);
        if(res == 0)
        {
            bsp_delay_ms(100);
            break;
        }
    }while(1);

    /* 发送 读取模块 指令 */
    uint8_t buff[6];
    e32_900_send_require_cmd(REG_TYPE_ADD_H, 0x06);
    bsp_delay_ms(100);
    uint32_t size = 0;
    drv->ops.ioctrl(drv, IOCTRL_GET_RX_BUFF_SIZE, &size);
    if((size != 0) && (size < 0xff))
    {
        for(uint8_t i = 0; i < size; i++)
        {
            uint8_t byte = 0;
            drv->ops.ioctrl(drv, IOCTRL_GET_RX_BUFF_BYTE, (uint32_t*)&byte);
            uint8_t res = e32_900_config_process(byte, buff);
            if(res != 0)
            {
                for (uint8_t i = 0; i < res; i++)
                {
                    SEGGER_RTT_printf(0, "reg <buff[0x%x]>.\r\n",buff[i]);
                }
                
                /* 读取的数据 与 配置的数据相等 */
                if(memcmp(buff, default_config, res) == 0)
                {
                    SEGGER_RTT_printf(0, "lora reg comparison completed.\r\n");
                    e32_900_config_work_mode(LORA_MODE_NORMAL);
                    return 0;
                }
            }
        }
    }

    e32_900_write_reg_cmd(default_config, 6);
    bsp_delay_ms(100);
    CTRL_POWER_3V3(0);
    bsp_delay_ms(100);
    CTRL_POWER_3V3(1);
    bsp_delay_ms(100);

    SEGGER_RTT_printf(0, "lora size = %d; reset power = %d.\r\n", size, times++);

    return -1;
}
